﻿using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;

namespace MouldingAndMillwork.SSIS
{
    #region CLASS: ColumnInformation
    public class ColumnInformation : System.Xml.Serialization.IXmlSerializable
    {
        #region Private Constants
        private const DataType DEFAULT_DATATYPE = DataType.DT_I4;
        private const int DEFAULT_FIELDLENGTH = 0;
        private const int DEFAULT_PRECISION = 0;
        private const int DEFAULT_SCALE = 0;
        private const int DEFAULT_CODEPAGE = 0;
        #endregion

        #region Private Variables
        #region Design-time
        private string _name;
        private int _lineageID;
        private DataType _dataType;
        private int _length;
        private int _precision;
        private int _scale;
        private int _codePage;
        #endregion

        #region Runtime
        private int _bufferIndex;
        #endregion
        #endregion

        #region Constructors
        public ColumnInformation(string name, int lineageID, DataType dataType, int length, int precision, int scale, int codePage)
        {
            this._name = name;
            this._lineageID = lineageID;
            this._dataType = dataType;
            this._length = length;
            this._precision = precision;
            this._scale = scale;
            this._codePage = codePage;
        }

        public ColumnInformation(IDTSOutputColumn100 outputColumn)
        {
            this._name = outputColumn.Name;
            this._lineageID = outputColumn.LineageID;
            this._dataType = outputColumn.DataType;
            this._length = outputColumn.Length;
            this._precision = outputColumn.Precision;
            this._scale = outputColumn.Scale;
            this._codePage = outputColumn.CodePage;
        }

        public ColumnInformation(IDTSInputColumn100 inputColumn)
        {
            this._name = inputColumn.Name;
            this._lineageID = inputColumn.LineageID;
            this._dataType = inputColumn.DataType;
            this._length = inputColumn.Length;
            this._precision = inputColumn.Precision;
            this._scale = inputColumn.Scale;
            this._codePage = inputColumn.CodePage;
        }

        public ColumnInformation(IDTSVirtualInputColumn100 vInputColumn)
        {
            this._name = vInputColumn.Name;
            this._lineageID = vInputColumn.LineageID;
            this._dataType = vInputColumn.DataType;
            this._length = vInputColumn.Length;
            this._precision = vInputColumn.Precision;
            this._scale = vInputColumn.Scale;
            this._codePage = vInputColumn.CodePage;
        }

        public ColumnInformation()
        {
            this._lineageID = -1;
        }
        #endregion

        #region Public Properties
        public bool IsValid
        {
            get { return this._lineageID >= 0; }
        }

        public string Name
        {
            get { return this._name; }
            set { this._name = value; }
        }

        public int LineageID
        {
            get { return this._lineageID; }
            set { this._lineageID = value; }
        }

        public DataType DataType
        {
            get { return this._dataType; }
            set { this._dataType = value; }
        }

        public int Length
        {
            get { return this._length; }
            set { this._length = value; }
        }

        public int Precision
        {
            get { return this._precision; }
            set { this._precision = value; }
        }

        public int Scale
        {
            get { return this._scale; }
            set { this._scale = value; }
        }

        public int CodePage
        {
            get { return this._codePage; }
            set { this._codePage = value; }
        }

        public int BufferIndex
        {
            get { return this._bufferIndex; }
            set { this._bufferIndex = value; }
        }
        #endregion

        #region Public Methods
        public void SetDataType(DataType dataType, int length, int precision, int scale, int codePage)
        {
            this._dataType = dataType;
            this._length = length;
            this._precision = precision;
            this._scale = scale;
            this._codePage = codePage;
        }
        #endregion

        #region IXmlSerializable Members
        public System.Xml.Schema.XmlSchema GetSchema()
        {
            return null;
        }

        public void ReadXml(System.Xml.XmlReader reader)
        {
            System.Xml.XmlReader safereader;
            using (safereader = reader.ReadSubtree())
            {
                while (safereader.ReadState != System.Xml.ReadState.EndOfFile)
                {
                    safereader.Read();
                    System.Xml.XmlNodeType type = safereader.MoveToContent();
                    if ((type == System.Xml.XmlNodeType.Element) && (safereader.LocalName == this.GetType().Name))
                    {
                        this._name = SSISUtility.CustomProperty.DeserializeProperty(safereader, "Name", null);
                        this._lineageID = SSISUtility.CustomProperty.DeserializeProperty(safereader, "LineageID", -1);
                        this._dataType = (DataType)SSISUtility.CustomProperty.DeserializeProperty(safereader, "DataType", (int)DEFAULT_DATATYPE);
                        this._length = SSISUtility.CustomProperty.DeserializeProperty(safereader, "Length", DEFAULT_FIELDLENGTH);
                        this._precision = SSISUtility.CustomProperty.DeserializeProperty(safereader, "Precision", DEFAULT_PRECISION);
                        this._scale = SSISUtility.CustomProperty.DeserializeProperty(safereader, "Scale", DEFAULT_SCALE);
                        this._codePage = SSISUtility.CustomProperty.DeserializeProperty(safereader, "CodePage", DEFAULT_CODEPAGE);
                    }
                }
            }
            reader.Read();
        }

        public void WriteXml(System.Xml.XmlWriter writer)
        {
            SSISUtility.CustomProperty.SerializeProperty(writer, "Name", this._name, null);
            SSISUtility.CustomProperty.SerializeProperty(writer, "LineageID", this._lineageID, -1);
            SSISUtility.CustomProperty.SerializeProperty(writer, "DataType", (int)this._dataType, (int)DEFAULT_DATATYPE);
            SSISUtility.CustomProperty.SerializeProperty(writer, "Length", this._length, DEFAULT_FIELDLENGTH);
            SSISUtility.CustomProperty.SerializeProperty(writer, "Precision", this._precision, DEFAULT_PRECISION);
            SSISUtility.CustomProperty.SerializeProperty(writer, "Scale", this._scale, DEFAULT_SCALE);
            SSISUtility.CustomProperty.SerializeProperty(writer, "CodePage", this._codePage, DEFAULT_CODEPAGE);
        }
        #endregion

        #region ToString
        public override string ToString()
        {
            return this._name + " (" + this._lineageID.ToString() + ")";
        }
        #endregion
    }
    #endregion

    #region CLASS: ColumnInformationList
    public class ColumnInformationList : List<ColumnInformation>
    {
        public ColumnInformationList()
        { }

        public ColumnInformation this[string columnName]
        {
            get
            {
                foreach (ColumnInformation columnInfo in this)
                {
                    if (columnInfo.Name == columnName)
                    {
                        return columnInfo;
                    }
                }

                throw new ArgumentOutOfRangeException("columnName", "Column '" + columnName + "' was not in the list.");
            }
        }

        public bool Contains(int lineageID)
        {
            foreach (ColumnInformation column in this)
            {
                if (column.LineageID == lineageID)
                {
                    return true;
                }
            }
            return false;
        }

        public int IndexOf(int lineageID)
        {
            for (int index = 0; index < this.Count; index++)
            {
                if (this[index].LineageID == lineageID)
                {
                    return index;
                }
            }
            return -1;
        }

        public ColumnInformationList(IDTSVirtualInputColumnCollection100 virtualColumns)
        {
            foreach (IDTSVirtualInputColumn100 virtualColumn in virtualColumns)
            {
                this.Add(new ColumnInformation(virtualColumn.Name, virtualColumn.LineageID,
                    virtualColumn.DataType, virtualColumn.Length, virtualColumn.Precision,
                    virtualColumn.Scale, virtualColumn.CodePage));
            }
        }
    }
    #endregion
}
